using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using FireStarterModeller.UI.DetailsView.Controller;
using Habanero.Base;
using Habanero.Base.Exceptions;
using Habanero.BO;

namespace FireStarterModeller.UI.DetailsView.WPF
{
    /// <summary>
    /// Interaction logic for SolutionAssemblyView.xaml
    /// </summary>
    public partial class SolutionAssemblyView : UserControl
    {
        public const int CONTROL_HEIGHT = 17;
        public const int EXPANDER_HEIGHT = 26;
        private bool _isSelected;
        private TextBox _newClassTextBox;
        private SolutionViewModel.ClassModel _selectedClassModel;
        private RenameItemPopup _renameClassPopup;

        public ISolutionViewController Controller { get; private set; }
        public SolutionViewModel.AssemblyModel Model { get; private set; }

        public Panel ClassesPanel
        {
            get { return _classesStackPanel; }
        }

        public Expander AssemblyExpander
        {
            get { return _assemblyExpander; }
        }

        public SolutionAssemblyView()
        {
            InitializeComponent();
        }

        public void Init(ISolutionViewController controller, SolutionViewModel.AssemblyModel model)
        {
            Controller = controller;
            Model = model;
            DataContext = Model;

            foreach (SolutionViewModel.ClassModel classModel in model.Classes)
            {
                _classesStackPanel.Children.Add(CreateClassTextBox(classModel));
            }

            Model.ClassAdded += classModel =>
                                {
                                    _classesStackPanel.Children.Insert
                                        (_classesStackPanel.Children.Count - 1, CreateClassTextBox(classModel));
                                    AssemblyExpander.IsExpanded = true;
                                    UpdateAssemblyExpanderHeight();
                                };

            Model.ClassRemoved += classModel =>
                                  {
                                      TextBox modelTextBox = GetTextBoxForClassModel(classModel);
                                      _classesStackPanel.Children.Remove(modelTextBox);
                                      AssemblyExpander.IsExpanded = true;
                                      UpdateAssemblyExpanderHeight();
                                  };

            Model.CurrentClassChanged += classModel =>
                                         {
                                             _selectedClassModel = classModel;
                                             foreach (TextBox textBox in _classesStackPanel.Children)
                                             {
                                                 if (textBox.Tag == _selectedClassModel) SelectTextBox(textBox);
                                                 else DeselectTextBox(textBox);
                                             }
                                         };

            _newClassTextBox = CreateClassTextBox();


            _newClassTextBox.PreviewKeyDown += (sender, e) =>
                                               {
                                                   if (e.Key != Key.Tab && e.Key != Key.Enter) return;
                                                   e.Handled = CreateClass();
                                               };

            _classesStackPanel.Children.Add(_newClassTextBox);
            _renameClassPopup = new RenameItemPopup();
            _renameClassPopup.OKButtonClicked += (sender, e) =>
                                                 {
                                                     if (
                                                         !RenameClass
                                                              ((SolutionViewModel.ClassModel)
                                                               _renameClassPopup.ItemToRename, _renameClassPopup.NewName))
                                                         return;
                                                     _renameClassPopup.IsOpen = false;
                                                 };
        }

        private TextBox GetTextBoxForClassModel(SolutionViewModel.ClassModel classModel)
        {
            TextBox modelTextBox = null;
            foreach (TextBox textBox in _classesStackPanel.Children)
            {
                if (textBox.Tag != classModel) continue;
                modelTextBox = textBox;
                break;
            }
            return modelTextBox;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns>Whether the Create was attempted or not (to help with whether to consume events etc)</returns>
        private bool CreateClass()
        {
            if (String.IsNullOrEmpty(_newClassTextBox.Text)) return false;
            try
            {
                Controller.CreateClass(Model, _newClassTextBox.Text);
                _newClassTextBox.Text = "";
            }
            catch (BusObjDuplicateConcurrencyControlException ex)
            {
                MessageBox.Show(ex.Message);
            }
            return true;
        }

        private TextBox CreateClassTextBox()
        {
            TextBox textBox = new TextBox();
            textBox.Style = ((Style) FindResource("ClassTextBoxStyle"));
            textBox.GotFocus += (sender, e) =>
                                {
                                    Controller.SelectAssembly(Model);
                                    Controller.SelectClass(Model, (SolutionViewModel.ClassModel) ((TextBox) sender).Tag);
                                };
            return textBox;
        }

        private TextBox CreateClassTextBox(SolutionViewModel.ClassModel classModel)
        {
            TextBox textBox = CreateClassTextBox();
            Binding nameTextBinding = new Binding("Name");
            nameTextBinding.Source = classModel;
            textBox.SetBinding(TextBox.TextProperty, nameTextBinding);

            textBox.Tag = classModel;

            ContextMenu contextMenu = new ContextMenu();
            MenuItem deleteMenuItem = new MenuItem();
            deleteMenuItem.Header = "Delete";
            deleteMenuItem.Click += (sender, e) => DeleteClass(classModel);
            contextMenu.Items.Add(deleteMenuItem);
            MenuItem renameMenuItem = new MenuItem();
            renameMenuItem.Header = "Rename";
            renameMenuItem.Click += (sender, e) => PopupRenameClass(classModel);
            contextMenu.Items.Add(renameMenuItem);
            textBox.ContextMenu = contextMenu;
            return textBox;
        }

        private void DeselectTextBox(TextBox textBox)
        {
            textBox.Style = (Style) FindResource("ClassTextBoxStyle");
        }

        private void SelectTextBox(TextBox textBox)
        {
            textBox.Style = (Style) FindResource("SelectedClassTextBoxStyle");
        }


        public bool IsSelected
        {
            get { return _isSelected; }
            internal set
            {
                _isSelected = value;
                UpdateIsSelectedVisual();
            }
        }

        public TextBox NewClassTextBox
        {
            get { return _newClassTextBox; }
        }

        public SolutionViewModel.ClassModel SelectedClassModel
        {
            get { return _selectedClassModel; }
        }

        private void UpdateIsSelectedVisual()
        {
            if (_isSelected)
            {
                _assemblyExpander.Style = (Style) FindResource("SelectedExpanderStyle");
            }
            else
            {
                _assemblyExpander.Style = (Style) FindResource("ExpanderStyle");
            }
        }

        private void _assemblyExpander_Expanded(object sender, RoutedEventArgs e)
        {
            UpdateAssemblyExpanderHeight();
        }

        private void UpdateAssemblyExpanderHeight()
        {
            int heightInControls = _classesStackPanel.Children.Count;
            int heightInPixels = EXPANDER_HEIGHT + heightInControls * CONTROL_HEIGHT;
            _assemblyExpander.Height = heightInPixels;
            _classesStackPanel.Height = heightInPixels;
            this.Height = heightInPixels;
            Controller.SelectAssembly(Model);
        }

        private void _assemblyExpander_Collapsed(object sender, RoutedEventArgs e)
        {
            _assemblyExpander.Height = EXPANDER_HEIGHT;
            this.Height = EXPANDER_HEIGHT;
            Controller.SelectAssembly(Model);
        }

        public void ForceCreateClass()
        {
            CreateClass();
        }

        private void DeleteClass(SolutionViewModel.ClassModel classModel)
        {
            Controller.DeleteClass(classModel);
        }

        public void ForceDeleteClass(SolutionViewModel.ClassModel classModel)
        {
            DeleteClass(classModel);
        }

        private void PopupRenameClass(SolutionViewModel.ClassModel classModel)
        {
            _renameClassPopup.Init(classModel, "Class", classModel.Name);
            _renameClassPopup.IsOpen = true;
        }

        public void ForceRenameClass(SolutionViewModel.ClassModel classModel, string newName)
        {
            RenameClass(classModel, newName);
        }

        private bool RenameClass(SolutionViewModel.ClassModel classModel, string newName)
        {
            try
            {
                Controller.RenameClass(classModel, newName);
                return true;
            }
            catch (HabaneroApplicationException ex)
            {
                GlobalRegistry.UIExceptionNotifier.Notify
                    (ex, "Problem renaming class '" + classModel.Name + "' to '" + newName + "'", "Note:");
                return false;
            }
        }
    }
}